home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / tracker-4.13.lha / tracker / Unix / ui.c
Encoding:
C/C++ Source or Header  |  1995-02-08  |  8.2 KB  |  458 lines

  1. /* unix/ui.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* special termio discipline for sun/sgi,
  6.  * for non blocking io and such.
  7.  * These functions should not be too difficult
  8.  * to write for a PC.
  9.  */
  10. /* $Id: ui.c,v 4.4 1995/02/08 13:47:35 espie Exp espie $
  11.  * $Log: ui.c,v $
  12.  * Revision 4.4  1995/02/08  13:47:35  espie
  13.  * *** empty log message ***
  14.  *
  15.  * Revision 4.3  1995/01/28  09:56:53  espie
  16.  * Port to FreeBSD/NeXTstep.
  17.  *
  18.  * Revision 4.2  1995/01/28  09:23:38  espie
  19.  * Support for old bsd io discipline (NeXT)
  20.  *
  21.  *
  22.  * Revision 4.0  1994/01/11  18:02:31  espie
  23.  * Major change: lots of new calls.
  24.  * Stupid termio bug: shouldn't restore term to sanity if we don't
  25.  * know what sanity is. For instance, if we haven't modified anything.
  26.  * cflags interpreted correctly.
  27.  * Hsavolai fix.
  28.  * Added bg/fg test.
  29.  */
  30.  
  31. #ifdef dec
  32. #define stub_only
  33. #endif
  34.  
  35. #ifdef __NeXT__
  36. #include <libc.h>
  37. #else /* __NeXT__ */
  38. #if defined(linux) || defined(__FreeBSD__)
  39. #include <termios.h>
  40. #else
  41. #ifdef __hpux
  42. #include <sys/bsdtty.h>
  43. #endif
  44. #include <sys/termio.h>
  45. #endif
  46. #ifdef __FreeBSD__
  47. #include <sys/ioctl.h>
  48. #define termio termios  /* hack to not touch many places */
  49. #endif
  50. #include <signal.h>
  51. #endif /* __NeXT__ */
  52. #include "defs.h"
  53. #include "extern.h"
  54. #include "tags.h"
  55. #include "prefs.h"
  56.  
  57.  
  58. LOCAL void nonblocking_io P((void));
  59. LOCAL void sane_tty P((void));
  60.  
  61. LOCAL void (*INIT)P((void)) = nonblocking_io;
  62.  
  63.  
  64. LOCAL int show;
  65. /* poor man's timer */
  66. LOCAL int current_pattern;
  67. LOCAL int count_pattern, count_song;
  68. #define SMALL_DELAY 25
  69.  
  70. /* do not define any stdio routines if it's known not to work */
  71.  
  72. #ifdef stub_only
  73.  
  74. int run_in_fg()
  75.    {
  76.    return TRUE;
  77.    }
  78.  
  79. LOCAL void sane_tty()
  80.    {
  81.    }
  82.  
  83. LOCAL struct tag end_marker;
  84.  
  85. struct tag *get_ui()
  86.    {
  87.    end_marker.type = TAG_END;
  88.    return &end_marker;
  89.    }
  90.  
  91. #else
  92.  
  93. #ifdef __NeXT__
  94. LOCAL struct sgttyb sanity;
  95. LOCAL struct sgttyb *psanity = 0;
  96. #else
  97. LOCAL struct termio sanity;
  98. LOCAL struct termio *psanity = 0;
  99. #endif
  100.  
  101. LOCAL int is_fg;
  102.  
  103. /* signal handler */
  104.  
  105. LOCAL void goodbye(sig)
  106. int sig;
  107.     {
  108.     static char buffer[25];
  109.  
  110.     sprintf(buffer, "Signal %d", sig);
  111.     end_all(buffer);
  112.     }
  113.  
  114. LOCAL void abort_this(sig)
  115. int sig;
  116.    {
  117.    end_all("Abort");
  118.    }
  119.  
  120. #ifdef SIGTSTP
  121. LOCAL void suspend(sig)
  122. int sig;
  123.    {
  124.    fflush(stdout);
  125.    sane_tty();
  126.    signal(SIGTSTP, SIG_DFL);
  127.    kill(0, SIGTSTP);
  128.    }
  129. #endif
  130.  
  131. int run_in_fg()
  132.    {
  133.    int val;
  134.  
  135. #ifdef __hpux
  136.     if (!isatty(fileno(stdin)) || !isatty(fileno(stdout)))
  137.         return FALSE;
  138. #endif
  139.  
  140.    /* real check for running in foreground */
  141.    if (ioctl(fileno(stdin), TIOCGPGRP, &val))
  142.       return FALSE;
  143. #ifdef __POSIX_SOURCE
  144.    if (val == getpgrp())
  145. #else
  146.    if (val == getpgrp(0))
  147. #endif
  148.       return TRUE;
  149.    else
  150.       return FALSE;
  151.    }
  152.  
  153. /* if_fg_sane_tty():
  154.  * restore tty modes, _only_ if running in foreground
  155.  */
  156. LOCAL void if_fg_sane_tty()
  157.     {
  158.     if (run_in_fg())
  159.         sane_tty();
  160.     }
  161.  
  162.  
  163. LOCAL void switch_mode()
  164.    {
  165. #ifdef __NeXT__
  166.    struct sgttyb zap;
  167.    int tty;
  168. #else
  169.    struct termio zap;
  170. #endif
  171.  
  172. #ifdef SIGTSTP
  173.    signal(SIGTSTP, suspend);
  174. #endif
  175.    signal(SIGCONT, switch_mode);
  176.    signal(SIGINT, goodbye);
  177.    signal(SIGQUIT, goodbye);
  178.    signal(SIGUSR1, abort_this);
  179.  
  180.    if (run_in_fg())
  181.       {
  182. #ifdef __NeXT__
  183.       tty = fileno(stdin);
  184.       fcntl(tty, F_SETFL, fcntl(tty, F_GETFL, 0) | FNDELAY);
  185.       ioctl(tty, TIOCGETP, &zap);
  186.       zap.sg_flags |= CBREAK;
  187.       zap.sg_flags &= ~ECHO;
  188.       ioctl(tty, TIOCSETP, &zap);
  189. #else /* __NeXT__ */
  190. #ifdef __FreeBSD__
  191.       tcgetattr(fileno(stdin), &zap);
  192. #else
  193.       ioctl(fileno(stdin), TCGETA, &zap);
  194. #endif
  195. #ifdef linux
  196.       zap.c_cc[VMIN] = 0;
  197.       zap.c_cc[VTIME] = 0;
  198. /* Commented out
  199. As Hannu said:
  200. The current Linux kernel interprets correctly the c_lflags field so it
  201. should be set like for the other systems. 
  202.       zap.c_lflag = 0;
  203.  */
  204. #else
  205. #ifdef __FreeBSD__
  206.       zap.c_cc[VMIN] = 0;     /* can't work with old */
  207.       zap.c_cc[VTIME] = 0; /* FreeBSD versions    */
  208.       zap.c_lflag &= ~(ICANON|ECHO|ECHONL);
  209. #endif
  210.       zap.c_cc[VEOL] = 0;
  211.       zap.c_cc[VEOF] = 0;
  212. #endif
  213.       zap.c_lflag &= ~(ICANON | ECHO);
  214. #ifdef __FreeBSD__
  215.       tcsetattr(fileno(stdin), TCSADRAIN, &zap);
  216. #else
  217.       ioctl(fileno(stdin), TCSETA, &zap);
  218. #endif
  219. #endif /* __NeXT__ */
  220.       is_fg = TRUE;
  221.       }
  222.    else
  223.       is_fg = FALSE;
  224.    }
  225.  
  226. /* nonblocking_io():
  227.  * try to setup the keyboard to non blocking io
  228.  */
  229. LOCAL void nonblocking_io()
  230.    {
  231.    show = get_pref_scalar(PREF_SHOW);
  232.  
  233.  
  234. #if 0 /* BROKEN */
  235.    /* try to renice our own process to get more cpu time */
  236.    if (nice(-15) == -1)
  237.       nice(0);
  238. #endif
  239.    if (!psanity)
  240.       {
  241.       psanity = &sanity;
  242. #ifdef __NeXT__
  243.       ioctl(fileno(stdin), TIOCGETP, psanity);
  244. #else /* __NeXT__ */
  245. #ifdef __FreeBSD__
  246.       tcgetattr(fileno(stdin), psanity);
  247. #else
  248.       ioctl(fileno(stdin), TCGETA, psanity);
  249. #endif
  250. #endif /* __NeXT__ */
  251.       }
  252.    switch_mode();
  253.    at_end(if_fg_sane_tty);
  254.    }
  255.  
  256.  
  257. /* sane_tty():
  258.  * restores everything to a sane state before returning to shell */
  259. LOCAL void sane_tty()
  260.    {
  261. #ifdef __NeXT__
  262.       ioctl(fileno(stdin), TIOCSETP, psanity);
  263. #else /* __NeXT__ */
  264. #ifdef __FreeBSD__
  265.       tcsetattr(fileno(stdin), TCSADRAIN, psanity);
  266. #else
  267.       ioctl(fileno(stdin), TCSETA, psanity);
  268. #endif
  269. #endif /* __NeXT__ */
  270.    }
  271.  
  272. LOCAL int may_getchar()
  273.    {
  274.    char buffer;
  275.  
  276.    INIT_ONCE;
  277.  
  278.    if (run_in_fg() && !is_fg)
  279.       switch_mode();
  280.    if (run_in_fg() && read(fileno(stdin), &buffer, 1))
  281.       return buffer;
  282.    return EOF;
  283.    }
  284.  
  285. LOCAL struct tag result[2];
  286.  
  287. struct tag *get_ui()
  288.    {
  289.    result[0].type = TAG_END;
  290.    result[1].type = TAG_END;
  291.    count_pattern++;
  292.    count_song++;
  293.    switch(may_getchar())
  294.       {
  295.    case 'n':
  296.       result[0].type = UI_NEXT_SONG;
  297.       break;
  298.    case 'p':
  299.       if (count_song > SMALL_DELAY)
  300.          result[0].type = UI_RESTART;
  301.       else
  302.          result[0].type = UI_PREVIOUS_SONG;
  303.       count_song = 0;
  304.       break;
  305.    case 'x':
  306.    case 'e':
  307.    case 'q':
  308.       result[0].type = UI_QUIT;
  309.       break;
  310.    case 's':
  311.       result[0].type = UI_SET_BPM;
  312.       result[0].data.scalar = 50;
  313.       break;
  314.    case 'S':
  315.       result[0].type = UI_SET_BPM;
  316.       result[0].data.scalar = 60;
  317.       break;
  318.    case '>':
  319.       result[0].type = UI_JUMP_TO_PATTERN;
  320.       result[0].data.scalar = current_pattern + 1;
  321.       break;
  322.    case '<':
  323.       result[0].type = UI_JUMP_TO_PATTERN;
  324.       result[0].data.scalar = current_pattern;
  325.       if (count_pattern < SMALL_DELAY)
  326.          result[0].data.scalar--;
  327.       break;
  328.    case '?':
  329.       show = !show;
  330.         set_pref_scalar(PREF_SHOW, show);
  331.         if (show)
  332.             putchar('\n');
  333.       break;
  334.    default:
  335.       break;
  336.       }
  337.    return result;
  338.    }
  339.       
  340.          
  341. #endif
  342.  
  343.  
  344. void notice(s)
  345. char *s;
  346.    {
  347.    fprintf(stderr, "%s\n", s);
  348.    }
  349.  
  350. void status(s)
  351. char *s;
  352.    {
  353.    if (run_in_fg())
  354.       {
  355.         if (s)
  356.          {
  357.          puts(s);
  358.          }
  359.       else
  360.          putchar('\n');
  361.       }
  362.    }
  363.  
  364. LOCAL char title[25];
  365. void song_title(s)
  366. char *s;
  367.    {
  368.     strncpy(title, s, 25);
  369.     if (run_in_fg() && !show)
  370.         puts(title);
  371.    count_song = 0;
  372.    }
  373.  
  374.  
  375. LOCAL char scroll_buffer[120];
  376.  
  377. GENERIC begin_info(title)
  378. char *title;
  379.    {
  380.    if (run_in_fg())
  381.       return scroll_buffer;
  382.    else
  383.       return 0;
  384.    }
  385.  
  386. void infos(handle, s)
  387. GENERIC handle;
  388. char *s;
  389.    {
  390.    if (handle)
  391.       printf(s);
  392.    }
  393.  
  394. void info(handle, line)
  395. GENERIC handle;
  396. char *line;
  397.    {
  398.    if (handle)
  399.       puts(line);
  400.    }
  401.  
  402. void end_info(handle)
  403. GENERIC handle;
  404.    {
  405.    if (handle)
  406.       fflush(stdout);
  407.    }
  408.  
  409. LOCAL char *last_result = 0;
  410.  
  411. char *new_scroll(void)
  412.    {
  413.    if (run_in_fg())
  414.       {
  415.       last_result = scroll_buffer;
  416.         if (get_pref_scalar(PREF_COLOR))
  417.           strcpy(scroll_buffer, "                    \033[0;39m\
  418. |                    \033[0;39m\
  419. ||                    \033[0;39m\
  420. |                    \033[0;39m");
  421.         else
  422.       strcpy(scroll_buffer, "             |             ||             |             ");
  423.  
  424.       }
  425.    else
  426.       last_result = 0;
  427.    return last_result;
  428.    }
  429.    
  430. void scroll()
  431.    {
  432.    if (run_in_fg() && last_result)
  433.         {
  434.       puts(scroll_buffer);
  435.         fflush(stdout);
  436.         }
  437.    }
  438.  
  439. void display_pattern(current, total, real)
  440. int current, total, real;
  441.    {
  442.    if (run_in_fg())
  443.       {
  444.       if (show)
  445.          printf("\n%3d/%3d[%3d] %s\n", current, total, real, title);
  446.       else
  447.          printf("%3d/%3d\b\b\b\b\b\b\b", current, total);
  448.       fflush(stdout); 
  449.       }
  450.    current_pattern = current;
  451.    count_pattern = 0;
  452.    }
  453.  
  454. int checkbrk()
  455.    {
  456.    return FALSE;
  457.    }
  458.